package com.tools.web.work.excel.poi;

import com.tools.common.object.Note;

import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

/**
 * 导入 Excel 时 Sheet 页的结构对象
 * */
@Note("导入 Excel 时 Sheet 页的结构对象")
public class SheetImporter {

    @Note("表头配置类")
    private final ExcelHead excelHead;

    @Note("导入读取 - 行数据处理器接口")
    private RowReadHandler<?> rowReadHandler;

    @Note("忽略读取的字段，即读取到了数据也不 set 值到对象的属性里")
    private Set<String> ignoreFieldSet;

    /* ************************************************************************************************************
     *
     *      构造器
     *
     * ************************************************************************************************************
     * */


    public SheetImporter(ExcelHead excelHead) {
        this(excelHead, null);
    }

    public SheetImporter(ExcelHead excelHead, RowReadHandler<?> rowReadHandler) {
        if(excelHead == null) throw new NullPointerException("表头配置类实例为 null");
        this.excelHead = excelHead;
        this.setRowReadHandler(rowReadHandler);
    }

    public static SheetImporter of(ExcelHead excelHead) {
        return new SheetImporter(excelHead);
    }

    public static SheetImporter of(ExcelHead excelHead, RowReadHandler<?> rowReadHandler) {
        return new SheetImporter(excelHead, rowReadHandler);
    }

    /* ************************************************************************************************************
     *
     *      Getter / Setter
     *
     * ************************************************************************************************************
     * */

    public ExcelHead getExcelHead() {
        return excelHead;
    }

    public RowReadHandler<?> getRowReadHandler() {
        return rowReadHandler;
    }

    public <T> RowReadHandler<T> getRowReadHandler(Class<T> valueType) {
        return (RowReadHandler<T>) rowReadHandler;
    }

    public void setRowReadHandler(RowReadHandler<?> rowReadHandler) {
        this.rowReadHandler = rowReadHandler;
    }

    public SheetImporter rowReadHandler(RowReadHandler<?> rowReadHandler) {
        this.setRowReadHandler(rowReadHandler);
        return this;
    }

    Set<String> getIgnoreFieldSet() {
        return ignoreFieldSet;
    }

    public int getMaxHeadRowNum() {
        return excelHead.getMaxHeadRowNum();
    }

    @Override
    public String toString() {
        return "SheetImporter{" +
                "rowReadHandler=" + rowReadHandler +
                ", excelHead=" + excelHead +
                ", ignoreFieldSet=" + ignoreFieldSet +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        SheetImporter that = (SheetImporter) o;
        return Objects.equals(excelHead, that.excelHead);
    }

    @Override
    public int hashCode() {
        return Objects.hash(excelHead);
    }


    /* ************************************************************************************************************
     *
     *      自定义方法
     *
     * ************************************************************************************************************
     * */


    public SheetImporter igField(String field) {
        this.private_lazyLoadIgnoreFieldSet();
        this.ignoreFieldSet.add(field);
        return this;
    }

    public SheetImporter igFields(String... fields) {
        if(fields == null || fields.length == 0) return this;
        this.private_lazyLoadIgnoreFieldSet();
        Collections.addAll(this.ignoreFieldSet, fields);
        return this;
    }

    public SheetImporter igFields(Iterable<String> fields) {
        if(fields == null) return this;
        this.private_lazyLoadIgnoreFieldSet();
        for(String field : fields) this.ignoreFieldSet.add(field);
        return this;
    }

    public SheetImporter delIgField(String field) {
        if(this.ignoreFieldSet == null || this.ignoreFieldSet.isEmpty()) return this;
        this.ignoreFieldSet.remove(field);
        return this;
    }

    public SheetImporter delIgFields(String... fields) {
        if(fields == null || fields.length == 0) return this;
        if(this.ignoreFieldSet == null || this.ignoreFieldSet.isEmpty()) return this;
        for(String field : fields) this.ignoreFieldSet.remove(field);
        return this;
    }

    public SheetImporter delIgFields(Iterable<String> fields) {
        if(fields == null) return this;
        if(this.ignoreFieldSet == null || this.ignoreFieldSet.isEmpty()) return this;
        for(String field : fields) this.ignoreFieldSet.remove(field);
        return this;
    }

    public SheetImporter clearIgnoreFieldSet() {
        if(this.ignoreFieldSet == null || this.ignoreFieldSet.isEmpty()) return this;
        this.ignoreFieldSet.clear();
        return this;
    }

    public boolean hasIgField(String field) {
        if(this.ignoreFieldSet == null || this.ignoreFieldSet.isEmpty()) return false;
        return this.ignoreFieldSet.contains(field);
    }

    public boolean hasIgAllField(String... fields) {
        if(fields == null || fields.length == 0) return false;
        if(this.ignoreFieldSet == null || this.ignoreFieldSet.isEmpty()) return false;
        for(String field : fields) if(!this.ignoreFieldSet.contains(field)) return false;
        return true;
    }

    public boolean hasIgAllField(Iterable<String> fields) {
        if(fields == null) return false;
        if(this.ignoreFieldSet == null || this.ignoreFieldSet.isEmpty()) return false;
        for(String field : fields) if(!this.ignoreFieldSet.contains(field)) return false;
        return true;
    }

    public boolean hasIgAnyField(String... fields) {
        if(fields == null || fields.length == 0) return false;
        if(this.ignoreFieldSet == null || this.ignoreFieldSet.isEmpty()) return false;
        for(String field : fields) if(this.ignoreFieldSet.contains(field)) return true;
        return false;
    }

    public boolean hasIgAnyField(Iterable<String> fields) {
        if(fields == null) return false;
        if(this.ignoreFieldSet == null || this.ignoreFieldSet.isEmpty()) return false;
        for(String field : fields) if(this.ignoreFieldSet.contains(field)) return true;
        return false;
    }

    public boolean ignoreFieldSetIsEmpty() {
        return this.ignoreFieldSet == null || this.ignoreFieldSet.isEmpty();
    }

    public int ignoreFieldCount() {
        return this.ignoreFieldSet == null ? 0 : this.ignoreFieldSet.size();
    }

    public Set<String> copyIgnoreFieldSet() {
        if(this.ignoreFieldSet == null || this.ignoreFieldSet.isEmpty()) return new HashSet<>();
        return new HashSet<>(this.ignoreFieldSet);
    }

    /* ************************************************************************************************************
     *
     *      私有逻辑
     *
     * ************************************************************************************************************
     * */

    @Note("懒加载忽略字段集合")
    private void private_lazyLoadIgnoreFieldSet() {
        if(this.ignoreFieldSet != null) return;
        synchronized (this) {
            if(this.ignoreFieldSet != null) return;
            this.ignoreFieldSet = new HashSet<>();
        }
    }
}
